package com.agileboot.api.customize.config;

import cn.hutool.json.JSONUtil;
import com.agileboot.api.customize.ApiTokenUtils;
import com.agileboot.common.enums.common.UserStatusEnum;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.app.user.db.AppUserService;
import com.agileboot.domain.app.user.db.AppUserEntity;
import com.agileboot.infrastructure.user.app.AppLoginUser;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 自定义加载用户信息通过用户名
 * 用于SpringSecurity 登录流程
 * 没有办法把这个类 放进loginService中  会在SecurityConfig中造成循环依赖
 *
 * @author valarchie
 * @see com.agileboot.infrastructure.config.SecurityConfig#filterChain(HttpSecurity)
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ApiUserDetailsService implements UserDetailsService {

    private final AppUserService userService;

    private final ApiTokenUtils apiTokenUtils;

    /**
     * 根据用户名加载用户信息
     * <p>
     * 这段代码触发 此 方法
     * authenticate(new UsernamePasswordAuthenticationToken(bean.getPhone(), "admin123"));
     *
     * @param username 用户名
     * @return 用户信息
     * @throws UsernameNotFoundException 如果用户不存在或已被停用，则抛出此异常
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        AppUserEntity userInfo = userService.getUserByUserName(username);

        log.error("qqz>>>>查询结果:" + JSONUtil.toJsonStr(userInfo));
        if (userInfo == null) {
            log.info("登录用户：{} 不存在.", username);
            throw new ApiException(ErrorCode.Business.USER_NON_EXIST, username);
        }
        if (!Objects.equals(UserStatusEnum.NORMAL.getValue(), userInfo.getStatus())) {
            log.info("登录用户：{} 已被停用.", username);
            throw new ApiException(ErrorCode.Business.USER_IS_DISABLE, username);
        }

        //   查询数据库中的密码丢给security 去匹配是否正确,错误则返回 账号或密码错误！
        AppLoginUser appLoginUser = new AppLoginUser(userInfo.getUserId(), userInfo.getPhone(), userInfo.getPassword());
        appLoginUser.fillLoginInfo();
        Long aLong = appLoginUser.getLoginInfo().getLoginTime() + TimeUnit.MINUTES.toMillis(apiTokenUtils.getAutoRefreshTime());
        appLoginUser.setAutoRefreshCacheTime(aLong);
        // 返回用户信息给security 去验证账号密码
        return appLoginUser;
    }


}
